//// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
//package com.linqingying.gitcode.pullrequest.ui.comment
//
//import com.intellij.collaboration.async.classAsCoroutineName
//import com.intellij.collaboration.async.combineState
//import com.intellij.collaboration.async.mapDataToModel
//import com.intellij.collaboration.async.mapState
//import com.intellij.collaboration.ui.codereview.comment.CodeReviewSubmittableTextViewModelBase
//import com.intellij.collaboration.ui.codereview.timeline.thread.CodeReviewResolvableItemViewModel
//import com.intellij.collaboration.util.SingleCoroutineLauncher
//import com.intellij.openapi.diagnostic.logger
//import com.intellij.openapi.progress.EmptyProgressIndicator
//import com.intellij.openapi.progress.ProcessCanceledException
//import com.intellij.openapi.project.Project
//import com.intellij.platform.util.coroutines.childScope
//import kotlinx.coroutines.CoroutineScope
//import kotlinx.coroutines.flow.*
//import kotlinx.coroutines.future.asDeferred
//import com.linqingying.gitcode.api.data.GCActor
//import com.linqingying.gitcode.api.data.pullrequest.GCPullRequestReviewComment
//import com.linqingying.gitcode.api.data.pullrequest.GCPullRequestReviewThread
//import com.linqingying.gitcode.pullrequest.comment.ui.GCPRNewThreadCommentViewModel
//import com.linqingying.gitcode.pullrequest.data.GCPRDataContext
//import com.linqingying.gitcode.pullrequest.data.provider.GCPRDataProvider
//import com.linqingying.gitcode.pullrequest.data.provider.GCPRReviewDataProvider
//import com.linqingying.gitcode.ui.avatars.GCAvatarIconsProvider
//import kotlin.coroutines.cancellation.CancellationException
//
///**
// * A viewmodel for a compact foldable review thread view
// */
//interface GCPRCompactReviewThreadViewModel : GCPRReviewThreadViewModel,
//                                             CodeReviewResolvableItemViewModel {
//  override val isBusy: StateFlow<Boolean>
//
//  val comments: StateFlow<List<CommentItem>>
//
//  override val canCreateReplies: StateFlow<Boolean>
//  val isWritingReply: StateFlow<Boolean>
//  override val newReplyVm: GCPRNewThreadCommentViewModel
//
//  fun startWritingReply()
//  fun stopWritingReply()
//
//  override val isResolved: StateFlow<Boolean>
//  override val canChangeResolvedState: StateFlow<Boolean>
//  override fun changeResolvedState()
//
//  sealed interface CommentItem {
//    data class Comment(val vm: GCPRReviewThreadCommentViewModel) : CommentItem
//    data class Expander(val collapsedCount: Int, val expand: () -> Unit) : CommentItem
//  }
//}
//
//private val LOG = logger<UpdateableGCPRCompactReviewThreadViewModel>()
//
//internal class UpdateableGCPRCompactReviewThreadViewModel(
//  private val project: Project,
//  parentCs: CoroutineScope,
//  private val dataContext: GCPRDataContext,
//  private val dataProvider: GCPRDataProvider,
//  initialData: GCPullRequestReviewThread
//) : GCPRCompactReviewThreadViewModel {
//  private val cs = parentCs.childScope(classAsCoroutineName())
//  private val reviewData: GCPRReviewDataProvider = dataProvider.reviewData
//  private val taskLauncher = SingleCoroutineLauncher(cs)
//
//  private val dataState = MutableStateFlow(initialData)
//
//  override val isBusy: StateFlow<Boolean> = taskLauncher.busy
//
//  override val id = initialData.id
//
//  override val avatarIconsProvider: GCAvatarIconsProvider = dataContext.avatarIconsProvider
//
//  private val commentsVms = dataState
//    .map { it.comments.withIndex() }
//    .mapDataToModel({ it.value.id }, { createComment(it) }, { update(it) })
//    .stateIn(cs, SharingStarted.Eagerly, emptyList())
//  private val repliesFolded = MutableStateFlow(initialData.comments.size > 3)
//
//  override val comments: StateFlow<List<GCPRCompactReviewThreadViewModel.CommentItem>> =
//    commentsVms.combineState(repliesFolded) { comments, folded ->
//      if (!folded || comments.size <= 3) {
//        comments.map { GCPRCompactReviewThreadViewModel.CommentItem.Comment(it) }
//      }
//      else {
//        listOf(
//          GCPRCompactReviewThreadViewModel.CommentItem.Comment(comments.first()),
//          GCPRCompactReviewThreadViewModel.CommentItem.Expander(comments.size - 2) { repliesFolded.value = false },
//          GCPRCompactReviewThreadViewModel.CommentItem.Comment(comments.last())
//        )
//      }
//    }
//
//  override val canCreateReplies: StateFlow<Boolean> = dataState.mapState { it.viewerCanReply }
//  private val _isWritingReply = MutableStateFlow(false)
//  override val isWritingReply: StateFlow<Boolean> = _isWritingReply.asStateFlow()
//  override val newReplyVm: GCPRNewThreadCommentViewModel = ReplyViewModel()
//
//  override val canChangeResolvedState: StateFlow<Boolean> =
//    dataState.mapState { it.viewerCanResolve || it.viewerCanUnresolve }
//  override val isResolved: StateFlow<Boolean> = dataState.mapState { it.isResolved }
//
//  override fun startWritingReply() {
//    _isWritingReply.value = true
//    newReplyVm.requestFocus()
//  }
//
//  override fun stopWritingReply() {
//    _isWritingReply.value = false
//  }
//
//  override fun changeResolvedState() {
//    val resolved = isResolved.value
//    taskLauncher.launch {
//      val newData = try {
//        if (resolved) {
//          reviewData.unresolveThread(EmptyProgressIndicator(), id)
//        }
//        else {
//          reviewData.resolveThread(EmptyProgressIndicator(), id)
//        }.asDeferred().await()
//      }
//      catch (e: Exception) {
//        if (e is ProcessCanceledException || e is CancellationException) return@launch
//        LOG.warn("Failed to change thread resolution", e)
//        return@launch
//      }
//      dataState.value = newData
//    }
//  }
//
//  fun update(data: GCPullRequestReviewThread) {
//    dataState.value = data
//  }
//
//  private fun CoroutineScope.createComment(comment: IndexedValue<GCPullRequestReviewComment>): UpdateableGCPRReviewThreadCommentViewModel =
//    UpdateableGCPRReviewThreadCommentViewModel(project, this, dataContext, dataProvider,
//                                               this@UpdateableGCPRCompactReviewThreadViewModel, comment)
//
//  private inner class ReplyViewModel
//    : CodeReviewSubmittableTextViewModelBase(project, cs, ""), GCPRNewThreadCommentViewModel {
//
//    override val currentUser: GCActor = dataContext.securityService.currentUser
//
//    override fun submit() {
//      val replyId = dataState.value.comments.firstOrNull()?.id ?: return
//      submit {
//        reviewData.addComment(EmptyProgressIndicator(), replyId, it).asDeferred().await()
//        text.value = ""
//      }
//    }
//  }
//}
